package com.chrray.position.mygenerator;

import com.chrray.position.mygenerator.entity.Column;
import com.chrray.position.mygenerator.entity.Table;
import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.Charset;
import java.sql.*;
import java.util.*;

/**
 * MyBatis连接MySQL数据库，生成实体类和DAO接口，以及映射配置文件的主类
 *
 * @author ZHANGWEI
 * @goal generate
 */
@Component
public class MybatisMysqlGenerator extends AbstractMojo {
    private String baseDic;
    private String configurationFile;
    private String baseDicPro;
    private String baseUrl;
    private String javaBaseUrl;
    private String moduleUrl;
    private String connectionURL;
    private String username;
    private String password;
    private String driverClass;
    private String packageName;
    private String packageUrl;
    private String xmlBaseUrl;

    public MybatisMysqlGenerator(String baseUrl, String javaBaseUrl, String moduleUrl, String connectionURL, String username, String password, String driverClass, String packageName, String packageUrl, String xmlBaseUrl) {
        this.baseUrl = baseUrl;
        this.javaBaseUrl = javaBaseUrl;
        this.moduleUrl = moduleUrl;
        this.connectionURL = connectionURL;
        this.username = username;
        this.password = password;
        this.driverClass = driverClass;
        this.packageName = packageName;
        this.packageUrl = packageUrl;
        this.xmlBaseUrl = xmlBaseUrl;
    }

    @Override
    public void execute() throws MojoExecutionException {
        getLog().info("MyBatis Mysql Generator start...");

        try {
            //1、加载配置文件
            CompositeConfiguration config = loadConfigFiles();
            //2、读取配置信息
            Map<String, String> configMap = readConfig(config);
            //3、读取MySQL数据库元数据
            List<Table> tableList = readMySQLDataBaseMetaData(configMap);

            //4、生成实体类
            //	生成基础父类
            generateBaseEntity(tableList);
            //	生成子类
            generateEntity(tableList);

            //生成基础DAO接口
            generateBaseAllDao(tableList);
            //生成DAO接口
            generateAllDao(tableList);

            //生成基础XML映射文件
            generateBaseAllXml(tableList);
            //生成基础XML映射文件
            generateAllXml(tableList);
            //7.生成service层 1基层base接口，2-接口，3-基本实现类，4-实现类
            generateAllService(tableList);

            //8.生成basercontroler和controller
            generateAllController(tableList);

            //生成列表html
            //copyTemp(configMap,tableList,"listPage.html","list.html");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成service
     * @param tableList
     * @throws IOException
     */
    private void generateAllController(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //获取controller的路径
        String controllerUrl = baseUrl + javaBaseUrl + packageUrl + "/" + "controller" + moduleUrl;
        //controller的包路径
        String controllerPackageName = packageName + "." + "controller." + moduleUrl.replaceAll("/", "");
        getLog().info(controllerUrl);
        String controllerPackagePath = controllerUrl.replaceAll("\\.", "/");

        //获取mapper的路径
        //获取entiy的路径
        String entityPackageName = packageName + "." + "entity." + moduleUrl.replaceAll("/", "");
        String servicerPackagePath = packageName + "." + "service." + moduleUrl.replaceAll("/", "");
        //判断基本接口保存路径包路径是否存在，如果不存在，则创建
        File packageFile = new File(controllerPackagePath);
        if (!packageFile.exists()) {
            packageFile.mkdirs();
        }
        //循环创建每一个
        for (Table table : tableList) {
            //编辑基础controller
            //包声明部分
            StringBuffer packageDeclare = new StringBuffer();
            //导入声明部分
            List<String> importDeclare = new ArrayList<String>();
            //类声明部分
            StringBuffer classBeginDeclare = new StringBuffer();
            //类声明结束部分
            StringBuffer classEndDeclare = new StringBuffer();
            //基础接口的编辑
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }

            //包声明(如果是base这里要加上packageName即base,如果是子类则packageName即拼接的是空字符)
            packageDeclare.append("package " + controllerPackageName + ";\r\n");
            //导入实体类路径
            importDeclare.add("import " + entityPackageName + "." + className + "Entity;\r\n");
            //导入service接口路径
            importDeclare.add("import " + servicerPackagePath + ".I" + className + "" + "Service" + ";\r\n");
            importDeclare.add("import org.springframework.beans.factory.annotation.Autowired;\r\n");
            importDeclare.add("import org.springframework.web.bind.annotation.*;\r\n");
//            importDeclare.add("import com.example.demo.util.page.ResultUtil;\r\n");
//            importDeclare.add("import com.github.pagehelper.Page;\r\n");
            importDeclare.add("import com.chrray.position.util.result.ResponseResult;\r\n");
//            importDeclare.add("import com.example.demo.util.uuid.UUIDUtils;\r\n");
//            importDeclare.add("import com.example.demo.exception.FailException;\r\n");
            importDeclare.add("import io.swagger.annotations.ApiOperation;\r\n");
            importDeclare.add("import io.swagger.annotations.Api;\r\n");
            //拼接后缀生成类名称
            //生成类描述
            classBeginDeclare.append("/**\r\n");
            classBeginDeclare.append(" *" + table.getRemarks() + "\r\n");
            classBeginDeclare.append(" *@author lm \r\n");
            classBeginDeclare.append(" */\r\n");
            classBeginDeclare.append(" @RestController\r\n");
            classBeginDeclare.append(" @RequestMapping(\"/api/" + className.substring(0, 1).toLowerCase() + className.substring(1) + "\")\r\n");
            classBeginDeclare.append(" @Api(value = \"" + table.getRemarks() + "\",tags = \"" + table.getRemarks() + "\")\r\n");
            classBeginDeclare.append("public class " + className + "Controller{\r\n");
            //方法声明部分
            List<String> methodDeclare = new ArrayList<String>();
            methodDeclare.add("\t @Autowired\r\n");
            methodDeclare.add("\t private I" + className + "Service  i" + className + "Service;\r\n");

            methodDeclare.add("\t/**\r\n");

            methodDeclare.add("\t * 查询全部 " + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t@ApiOperation(value = \"查询" + table.getRemarks() + "方法\")\r\n");
            methodDeclare.add("\t@GetMapping(value=\"/selectAll\")\r\n");
            methodDeclare.add("\t public ResponseResult selectAll(" + className + "Entity entity){\r\n"
                + "\t      return i" + className + "Service.selectAll(entity);\r\n"
                + "\t}\r\n");

            methodDeclare.add("\t/**\r\n");
            methodDeclare.add("\t * 根据ID查询 " + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t@ApiOperation(value = \"根据ID查询" + table.getRemarks() + "方法\")\r\n");
            methodDeclare.add("\t@GetMapping(value=\"/selectById\")\r\n");
            methodDeclare.add("\t public ResponseResult selectById(" + className + "Entity obj){\r\n"
                + "\t\treturn  i" + className + "Service.selectById(obj);"
                + "\n\t}\r\n\r\n");

            methodDeclare.add("\t/**\r\n");
            methodDeclare.add("\t * 添加数据" + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t @ApiOperation(value = \"新增" + table.getRemarks() + "方法\")\r\n");
            methodDeclare.add("\t @PostMapping(value=\"/insert\")\r\n");
            methodDeclare.add("\t public ResponseResult insert(" + className + "Entity obj)  {\r\n"
                + "\t       return i" + className + "Service.insert(obj);\r\n"
                + "\t}\r\n");


            methodDeclare.add("\t/**\r\n");
            methodDeclare.add("\t * 修改" + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t @ApiOperation(value = \"修改" + table.getRemarks() + "方法\")\r\n");
            methodDeclare.add("\t @PostMapping(value=\"/updateById\")\r\n");
            methodDeclare.add("\t public ResponseResult updateById(" + className + "Entity obj) {\r\n"
                + "\t\treturn i" + className + "Service.updateById(obj);\r\n"
                + "\t}\r\n");
            //类声明——结束
            classEndDeclare.append("}\r\n");

            BufferedWriter bw = null;
            File controllerFile = new File(controllerPackagePath, (className + "Controller") + ".java");
            if (controllerFile.exists()) {
                continue;
            }
            if (!controllerFile.exists()) {
                packageFile.mkdirs();
            }
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(controllerFile), Charset.forName("UTF-8")));
                bw.write(packageDeclare.toString());
                for (String importStr : importDeclare) {
                    bw.write(importStr);
                }
                bw.write(classBeginDeclare.toString());
                for (String methodStr : methodDeclare) {
                    bw.write(methodStr.toString());
                }
                bw.write(classEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
                ;
            }


            //编辑controller
            //包声明部分
            StringBuffer bpackageDeclare = new StringBuffer();
            //导入声明部分
            List<String> bimportDeclare = new ArrayList<String>();
            //类声明部分
            StringBuffer bclassBeginDeclare = new StringBuffer();
            //类声明结束部分
            StringBuffer bclassEndDeclare = new StringBuffer();
            //包声明(如果是base这里要加上packageName即base,如果是子类则packageName即拼接的是空字符)
            bpackageDeclare.append("package " + controllerPackageName + ";\r\n\r\n");
            //导入service接口路径
            bimportDeclare.add("import " + controllerPackageName + ".I" + className + "" + "Service" + ";\r\n");
            //导入service接口路径
            bimportDeclare.add("import " + controllerPackageName + ".base." + className + "" + "BaseController" + ";\r\n");
            //导入list
            bimportDeclare.add("import org.springframework.beans.factory.annotation.Autowired;\r\n");
            bimportDeclare.add("import org.springframework.web.bind.annotation.RequestMapping;\r\n");
            bimportDeclare.add("import org.springframework.stereotype.Controller;\r\n");
            importDeclare.add("import com.chrray.position.util.result.ResponseResult;\r\n");
            //拼接后缀生成类名称
            //生成类描述
            bclassBeginDeclare.append("/*\r\n");
            bclassBeginDeclare.append(" *" + table.getRemarks() + "\r\n");
            bclassBeginDeclare.append(" */\r\n");
            bclassBeginDeclare.append("@Controller\r\n");
            bclassBeginDeclare.append("@RequestMapping(\"api/" + className.substring(0, 1).toLowerCase() + className.substring(1) + "\")\r\n");
            bclassBeginDeclare.append("public class " + className + "Controller extends " + className + "BaseController" + " {\r\n");
            bclassBeginDeclare.append("\t@Autowired\r\n");
            bclassBeginDeclare.append("\tprivate I" + className + "Service i" + className + "Service;\r\n");
            //类声明——结束
            bclassEndDeclare.append("}\r\n");

            BufferedWriter bbw = null;
            File bcontrollerFile = new File(controllerPackagePath, (className + "Controller") + ".java");
            if (bcontrollerFile.exists()) {
                continue;
            }
            try {
                bbw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(bcontrollerFile), Charset.forName("UTF-8")));
                bbw.write(bpackageDeclare.toString());
                for (String importStr : bimportDeclare) {
                    bbw.write(importStr);
                }
                bbw.write(bclassBeginDeclare.toString());
                bbw.write(bclassEndDeclare.toString());
            } finally {
                if (bbw != null) {
                    bbw.close();
                }
                ;
            }
        }
    }

    /**
     * 生成service
     *
     * @param tableList
     * @throws IOException
     */
    private void generateAllService(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //获取service的路径
        String serviceUrl = baseUrl + javaBaseUrl + packageUrl + "/" + "service" + moduleUrl;
        //service的包路径
        String servicePackageName = packageName + "." + "service." + moduleUrl.replaceAll("/", "");
        String mapperPackageName = packageName + "." + "mapper." + moduleUrl.replaceAll("/", "");
        getLog().info(serviceUrl);
        String servicePackagePath = serviceUrl.replaceAll("\\.", "/");
        //获取mapper的路径
        //获取entiy的路径
        String entityPackageName = packageName + "." + "entity." + moduleUrl.replaceAll("/", "");
        getLog().info(entityPackageName);
        //判断基本接口保存路径包路径是否存在，如果不存在，则创建
        File packageFile = new File(servicePackagePath);
        if (!packageFile.exists()) {
            packageFile.mkdirs();
        }
        File packageFileImple = new File(servicePackagePath + "/impl");
        if (!packageFileImple.exists()) {
            packageFileImple.mkdirs();
        }
        //循环创建每一个
        for (Table table : tableList) {
            //编辑基础接口
            //包声明部分
            StringBuffer BpackageDeclare = new StringBuffer();
            //导入声明部分
            List<String> BimportDeclare = new ArrayList<String>();
            //类声明部分
            StringBuffer BclassBeginDeclare = new StringBuffer();
            //类声明结束部分
            StringBuffer BclassEndDeclare = new StringBuffer();
            //基础接口的编辑
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }

            //包声明(如果是base这里要加上packageName即base,如果是子类则packageName即拼接的是空字符)
            BpackageDeclare.append("package " + servicePackageName + ";\r\n");
            //导入实体类路径
            BimportDeclare.add("import " + entityPackageName + "." + className + "Entity;\r\n");
            //导入list
//            BimportDeclare.add("import com.github.pagehelper.Page;\r\n");
            BimportDeclare.add("import com.chrray.position.util.result.ResponseResult;\r\n");
//            BimportDeclare.add("import com.chrray.position.util.result.ResponseResults;\r\n");
//            BimportDeclare.add("import "+packageName+".exception.FailException;\r\n");
            //拼接后缀生成类名称
            //生成类描述
            BclassBeginDeclare.append("/**\r\n");
            BclassBeginDeclare.append(" *" + table.getRemarks() + "\r\n");
            BclassBeginDeclare.append(" */\r\n");
            BclassBeginDeclare.append("public interface I" + className + "Service" + " {\r\n");
            //方法声明部分
            List<String> BmethodDeclare = new ArrayList<String>();
            BmethodDeclare.add("\t/**\r\n");
            BmethodDeclare.add("\t * 查询全部 " + table.getRemarks() + "\r\n");
            BmethodDeclare.add("\t */\r\n");
            BmethodDeclare.add("\t ResponseResult selectAll(" + className + "Entity entity);\r\n\r\n");
            BmethodDeclare.add("\t/**\r\n");
            BmethodDeclare.add("\t * 根据ID查询 " + table.getRemarks() + "\r\n");
            BmethodDeclare.add("\t */\r\n");
            BmethodDeclare.add("\t ResponseResult selectById(" + className + "Entity entity);\r\n\r\n");

            BmethodDeclare.add("\t/**\r\n");
            BmethodDeclare.add("\t * 添加数据" + table.getRemarks() + "\r\n");
            BmethodDeclare.add("\t */\r\n");
            BmethodDeclare.add("\t ResponseResult insert(" + className + "Entity entity);\r\n\r\n");

            BmethodDeclare.add("\t/**\r\n");
            BmethodDeclare.add("\t * 修改" + table.getRemarks() + "\r\n");
            BmethodDeclare.add("\t */\r\n");
            BmethodDeclare.add("\t ResponseResult updateById(" + className + "Entity entity);\r\n\r\n");
            //类声明——结束
            BclassEndDeclare.append("}\r\n");

            BufferedWriter Bbw = null;
            File BserviceFile = new File(servicePackagePath, ("I" + className + "Service") + ".java");
            if (BserviceFile.exists()) {
                continue;
            }
            try {
                Bbw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(BserviceFile), Charset.forName("UTF-8")));
                Bbw.write(BpackageDeclare.toString());
                for (String importStr : BimportDeclare) {
                    Bbw.write(importStr);
                }
                Bbw.write(BclassBeginDeclare.toString());
                for (String methodStr : BmethodDeclare) {
                    Bbw.write(methodStr.toString());
                }
                Bbw.write(BclassEndDeclare.toString());
            } finally {
                if (Bbw != null) {
                    Bbw.close();
                }
                ;
            }


            //包声明部分
            StringBuffer packageDeclare = new StringBuffer();
            //导入声明部分
            List<String> importDeclare = new ArrayList<String>();
            //类声明部分
            StringBuffer classBeginDeclare = new StringBuffer();
            //类声明结束部分
            StringBuffer classEndDeclare = new StringBuffer();

            //基础实现类的编辑
            //包声明(如果是base这里要加上packageName即base,如果是子类则packageName即拼接的是空字符)
            packageDeclare.append("package " + servicePackageName + ".impl;\r\n");
            //导入实体类路径
            importDeclare.add("import " + entityPackageName + "." + className + "Entity;\r\n");
            //导入dao路径
            importDeclare.add("import " + mapperPackageName + "." + className + "Mapper" + ";\r\n");
            //导入注解包
            importDeclare.add("import org.springframework.beans.factory.annotation.Autowired;\r\n");
            importDeclare.add("import " + servicePackageName + ".I" + className + "Service;\r\n");
            importDeclare.add("import org.springframework.stereotype.Service;\r\n");
            importDeclare.add("import com.github.pagehelper.PageHelper;\r\n");
            importDeclare.add("import com.github.pagehelper.Page;\r\n");
            importDeclare.add("import com.chrray.position.util.result.ResponseResult;\r\n");
            importDeclare.add("import com.chrray.position.util.result.ResponseResults;\r\n");
            importDeclare.add("import tk.mybatis.mapper.entity.Example;\r\n");
            importDeclare.add("import org.springframework.transaction.annotation.Transactional;\r\n");
//            importDeclare.add("import "+packageName+".exception.FailException;\r\n");
            //拼接后缀生成类名称
            //生成类描述
            classBeginDeclare.append("/**\r\n");
            classBeginDeclare.append(" *" + table.getRemarks() + "\r\n");
            classBeginDeclare.append(" */\r\n");
            classBeginDeclare.append("@Service\r\n");
            classBeginDeclare.append("public class " + className + "ServiceImpl" + "  implements I" + className + "Service {\r\n");
            //导入注解
            classBeginDeclare.append("\t @Autowired\r\n");
            //注入dao
            classBeginDeclare.append("\t private " + className + "Mapper  " + className.substring(0, 1).toLowerCase() + className.substring(1) + "Mapper; \r\n");
            getLog().info(classBeginDeclare.toString());
            //方法声明部分
            List<String> methodDeclare = new ArrayList<String>();
            methodDeclare.add("\t/**\r\n");
            methodDeclare.add("\t * 查询全部 " + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t @Override\r\n");
            methodDeclare.add("\t public ResponseResult selectAll(" + className + "Entity entity){\r\n"
                + "\t\tPageHelper.startPage(entity.getPage(),entity.getRows());\r\n "
                + "\t\tExample example = Example.builder(" + className + "Entity.class).build();\r\n " +
                "\t\tPage<" + className + "Entity> list =  (Page<" + className + "Entity>)" + className.substring(0, 1).toLowerCase() + className.substring(1) + "Mapper.selectByExample(example);\r\n" +
                "\t\treturn ResponseResults.success(list, \"查询" + table.getRemarks() + "数据成功\");" +
                "\r\t}" +
                "\r\n\r\n");
            methodDeclare.add("\t/**\r\n");


            methodDeclare.add("\t * 根据ID查询 " + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t @Override\r\n");
            methodDeclare.add("\t public ResponseResult selectById(" + className + "Entity obj){\r\n          return ResponseResults.success(" +
                className.substring(0, 1).toLowerCase() + className.substring(1) + "Mapper.selectByPrimaryKey(obj),\"查询" + table.getRemarks() + "数据成功\");"
                + "\r\n      }\r\n\r\n");

            methodDeclare.add("\t/**\r\n");
            methodDeclare.add("\t * 添加数据" + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t @Override\r\n");
            methodDeclare.add("\t public ResponseResult insert(" + className + "Entity obj) {\r\n \t\t"
                + className.substring(0, 1).toLowerCase() + className.substring(1) + "Mapper.insertSelective(obj);\n"
                + "\t\treturn ResponseResults.success(\"添加" + table.getRemarks() + "数据成功\");"
                + "\r\n      }\r\n\r\n");

            methodDeclare.add("\t/**\r\n");
            methodDeclare.add("\t * 修改" + table.getRemarks() + "\r\n");
            methodDeclare.add("\t */\r\n");
            methodDeclare.add("\t @Override\r\n");
            methodDeclare.add("\t @Transactional(rollbackFor = Exception.class) \r\n");
            methodDeclare.add("\t public ResponseResult updateById(" + className + "Entity obj) {\r\n "
                + "\t\tint num = " + className.substring(0, 1).toLowerCase() + className.substring(1) + "Mapper.updateByPrimaryKeySelective(obj);\r\n "
                + " \t\treturn  ResponseResults.success(\"修改" + table.getRemarks() + "数据成功\");"
                + "\r\n\t}");
            //类声明——结束
            classEndDeclare.append("\r\n}");

            BufferedWriter bw = null;
            File serviceFile = new File(servicePackagePath + "/impl", (className + "ServiceImpl") + ".java");
            if (serviceFile.exists()) {
                continue;
            }
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(serviceFile), Charset.forName("UTF-8")));
                bw.write(packageDeclare.toString());
                for (String importStr : importDeclare) {
                    bw.write(importStr);
                }
                bw.write(classBeginDeclare.toString());
                for (String methodStr : methodDeclare) {
                    bw.write(methodStr.toString());
                }
                bw.write(classEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
                ;
            }
        }
    }

    /**
     * 加载配置文件方法
     *
     * @return
     * @throws
     */
    private CompositeConfiguration loadConfigFiles() throws Exception {
        getLog().info("start read config files...");
        Properties pro = new Properties();
        InputStream inStream = MybatisMysqlGenerator.class.getClassLoader().getResourceAsStream("config/mybatis/mygenerator.properties");
        pro.load(inStream);
        baseDic = pro.getProperty("base_url");
        System.out.println(baseDic);
        configurationFile = pro.getProperty("generator_url");
        baseDicPro = pro.getProperty("generator_pro_url");
        //读取XML主配置文件
        CompositeConfiguration config = new CompositeConfiguration();
        getLog().info("configurationFile: " + baseDic + configurationFile);
        File f = new File(baseDic + configurationFile);

        config.addConfiguration(new XMLConfiguration(f));

        //如果存在，则读取Properties属性配置文件
		/*String propertiesFileName = config.getString("properties[@resource]");
		if (propertiesFileName!=null) {
			propertiesFileName = baseDir.getPath() + "/" + propertiesFileName;
		}*/
        String propertiesFileName = baseDic + baseDicPro;
        getLog().info("propertiesFileName: " + (propertiesFileName != null ? propertiesFileName : "null"));
        if (propertiesFileName != null) {
            config.addConfiguration(new PropertiesConfiguration(propertiesFileName));
        }

        getLog().info("read config files finished...");
        return config;
    }

    /**
     * 读取配置项方法
     *
     * @param config
     * @return
     */
    private Map<String, String> readConfig(CompositeConfiguration config) {
        Map<String, String> configMap = new HashMap<String, String>();

        //读取JDBC基本连接属性
        String driverClass = config.getString("jdbcConnection[@driverClass]");
        if (driverClass == null) {
            throw new RuntimeException("can't read driverClass config.");
        }
        configMap.put("driverClass", driverClass);

        String connectionURL = config.getString("jdbcConnection[@connectionURL]");
        if (connectionURL == null) {
            throw new RuntimeException("can't read connectionURL config.");
        }
        configMap.put("connectionURL", connectionURL);

        String userId = config.getString("jdbcConnection[@userId]");
        if (userId == null) {
            throw new RuntimeException("can't read userId config.");
        }
        configMap.put("userId", userId);

        String password = config.getString("jdbcConnection[@password]");
        if (password == null) {
            throw new RuntimeException("can't read password config.");
        }
        configMap.put("password", password);

        getLog().info("driverClass: " + driverClass);
        getLog().info("connectionURL: " + connectionURL);
        getLog().info("userId: " + userId);
        getLog().info("password: " + password);

        //读取实体类生成的存储包名
        String entityPackage = config.getString("entityGenerator[@targetPackage]");
        if (entityPackage == null) {
            throw new RuntimeException("can't read entityGenerator targetPackage config.");
        }
        configMap.put("entityPackage", entityPackage);
        getLog().info("entityPackage: " + entityPackage);

        //读取XML映射文件生成的存储包名
        String xmlPackage = config.getString("xmlGenerator[@targetPackage]");
        if (xmlPackage == null) {
            throw new RuntimeException("can't read xmlGenerator targetPackage config.");
        }
        configMap.put("xmlPackage", xmlPackage);
        getLog().info("xmlPackage: " + xmlPackage);

        //读取DAO接口生成的存储包名
        String daoPackage = config.getString("daoGenerator[@targetPackage]");
        if (daoPackage == null) {
            throw new RuntimeException("can't read daoGenerator targetPackage config.");
        }
        configMap.put("daoPackage", daoPackage);
        getLog().info("daoPackage: " + daoPackage);

        //读取service
        String servicePackage = config.getString("serviceGenerator[@targetPackage]");
        if (servicePackage == null) {
            throw new RuntimeException("can't read serviceGenerator targetPackage config.");
        }
        configMap.put("servicePackage", servicePackage);
        getLog().info("servicePackage: " + servicePackage);

        //读取controller配置
        String controllerPackage = config.getString("controllerGenerator[@targetPackage]");
        if (controllerPackage == null) {
            throw new RuntimeException("can't read controllerGenerator targetPackage config.");
        }
        configMap.put("controllerPackage", controllerPackage);
        getLog().info("controllerPackage: " + controllerPackage);

        //读取html模板配置
        String baesHtmlPackage = config.getString("baseHtmlGenerator[@targetPackage]");
        if (baesHtmlPackage == null) {
            throw new RuntimeException("can't read baesHtmlPackage targetPackage config.");
        }
        configMap.put("baesHtmlPackage", baesHtmlPackage);
        getLog().info("baesHtmlPackage: " + baesHtmlPackage);
        //获取html保存模板路径
        String saveHtmlPackage = config.getString("saveHtmlGenerator[@targetPackage]");
        if (saveHtmlPackage == null) {
            throw new RuntimeException("can't read saveHtmlPackage targetPackage config.");
        }
        configMap.put("saveHtmlPackage", saveHtmlPackage);
        getLog().info("saveHtmlPackage: " + saveHtmlPackage);
        //读取需要生成的表名
        String tableName = config.getString("table[@tableName]");
        if (tableName == null) {
            throw new RuntimeException("can't read table tableName config.");
        }
        configMap.put("tableName", tableName);
        getLog().info("tableName: " + tableName);

        return configMap;
    }

    /**
     * 读取MySQL数据库元数据方法
     *
     * @param configMap
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private List<Table> readMySQLDataBaseMetaData(Map<String, String> configMap) throws ClassNotFoundException, SQLException {
        List<Table> tableList = new ArrayList<Table>();
        Connection conn = null;
        ResultSet rs = null;
        try {
            //加载驱动，连接MySQL数据库，获取元数据
            Class.forName(driverClass);
            Properties props = new Properties();
            props.setProperty("user", username);
            props.setProperty("password", password);
            props.setProperty("remarks", "true");
            props.setProperty("useInformationSchema", "true");
            conn = DriverManager.getConnection(connectionURL, props);
            DatabaseMetaData dbMetaData = conn.getMetaData();
            //从元数据中读取表信息
            String[] tableTypes = {"TABLE"};
            String tableName = configMap.get("tableName");
            if(tableName.equals("*")){
                rs = dbMetaData.getTables(null, null, null, tableTypes);
                while (rs.next()) {
                    Table table = new Table();
                    //表名
                    table.setName(rs.getString("TABLE_NAME"));
                    //备注
                    table.setRemarks(rs.getString("REMARKS"));
                    tableList.add(table);
                }
            }else {
                String[] split = tableName.split("/");
                for (int i = 0; i < split.length; i++) {
                    ResultSet   rs1 = dbMetaData.getTables(null, null, split[i], tableTypes);
                    while (rs1.next()) {
                        Table table = new Table();
                        //表名
                        table.setName(rs1.getString("TABLE_NAME"));
                        //备注
                        table.setRemarks(rs1.getString("REMARKS"));
                        tableList.add(table);
                    }
                }

            }




            //从元数据中读取每张表的主键字段信息
            for (Table table : tableList) {
                rs = dbMetaData.getPrimaryKeys(null, null, table.getName());
                while (rs.next()) {
                    table.setPkName(rs.getString("COLUMN_NAME"));
                }
            }
            //从元数据中读取每张表的字段信息
            for (Table table : tableList) {
                rs = dbMetaData.getColumns(null, null, table.getName(), "%");
                while (rs.next()) {
                    Column column = new Column();
                    column.setName(rs.getString("COLUMN_NAME"));
                    column.setTypeName(rs.getString("TYPE_NAME"));
                    column.setRemarks(rs.getString("REMARKS"));
                    System.err.println(table.getPkName());
                    if (rs.getString("IS_NULLABLE").equals("YES")) {
                        column.setIsNotNull(true);
                    } else {
                        column.setIsNotNull(false);
                    }
                    if (rs.getString("COLUMN_NAME").equals(table.getPkName())) {
                        column.setIsPk(true);
                    } else {
                        column.setIsPk(false);
                    }
                    table.addColumn(column);
                }
            }

        } finally {
            if (rs != null && !rs.isClosed()) {
                rs.close();
            }
            if (conn != null && !conn.isClosed()) {
                conn.close();
            }
        }

        return tableList;
    }

    /**
     * 生成基础实体类方法
     *
     * @param tableList
     * @throws IOException
     */
    private void generateEntity(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //获取实体的路径
        String entityPackage = baseUrl + javaBaseUrl + this.packageUrl + "/" + "entity" + moduleUrl;
        getLog().info(entityPackage);
        //判断实体保存路径包路径是否存在，如果不存在，则创建
        File entityPackageFile = new File(entityPackage);
        if (!entityPackageFile.exists()) {
            entityPackageFile.mkdirs();
        }
        //循环创建每一个实体类
        for (Table table : tableList) {
            //包声明部分
            StringBuffer packageDeclare = new StringBuffer();
            //导入声明部分
            List<String> importDeclare = new ArrayList<String>();
            //类声明部分
            StringBuffer classBeginDeclare = new StringBuffer();
            //私有属性声明部分
            List<String> privatePropertyDeclare = new ArrayList<String>();
            //类声明结束部分
            StringBuffer classEndDeclare = new StringBuffer();
            //包名
            String packageName = this.packageName + "." + "entity." + moduleUrl.replaceAll("/", "");
            packageDeclare.append("package " + packageName + ";\r\n\r\n");
            //类声明——开始（将表名首字母大写，去掉_，并将第一个字母大写）
            //拼接后缀生成类名称
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }
            //生成类描述
            classBeginDeclare.append("/**\r\n");
            classBeginDeclare.append(" *" + table.getRemarks() + "\r\n");
            classBeginDeclare.append(" *@author lm \r\n");
            classBeginDeclare.append("**/\r\n");
            classBeginDeclare.append("@Entity\r\n");
            classBeginDeclare.append("@Data\r\n");
            classBeginDeclare.append("@ApiModel(value =\"" + table.getRemarks() + "\",description = \"" + table.getRemarks() + "\")\r\n");
            getLog().info(classBeginDeclare.toString());
            //子类
            classBeginDeclare.append("public class " + className + "Entity extends  " + className + "BaseEntity{\n");
            //生成类描述——结束
            classEndDeclare.append("\r\n}\r\n");
            //继承基础base
            String basePackageName = packageName + "." + "base." + className + "BaseEntity";
            importDeclare.add("import " + basePackageName + ";\r\n");
            importDeclare.add("import io.swagger.annotations.ApiModel;\r\n");
            importDeclare.add("import lombok.Data;\r");
            importDeclare.add("import javax.persistence.Entity;\r\n");
            importDeclare.add("\r\n");
//			写文件操作，如果是子类，文件存在则不写入
            File entityFile = null;
            entityFile = new File(entityPackage, className + "Entity.java");
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(entityFile), Charset.forName("UTF-8")));
                bw.write(packageDeclare.toString());
                for (String importStr : importDeclare) {
                    bw.write(importStr);
                }
                bw.write(classBeginDeclare.toString());
                for (String privatePropertyStr : privatePropertyDeclare) {
                    bw.write(privatePropertyStr.toString());
                }
                bw.write(classEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
            }
        }
    }

    /**
     * 生成基础实体类方法
     *
     * @param tableList
     * @throws IOException
     */
    private void generateBaseEntity(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //获取实体的路径
        String entityPackage = baseUrl + javaBaseUrl + this.packageUrl + "/" + "entity" + moduleUrl + "/" + "base";
        getLog().info(entityPackage);
        //判断实体保存路径包路径是否存在，如果不存在，则创建
        File entityPackageFile = new File(entityPackage);
        if (!entityPackageFile.exists()) {
            entityPackageFile.mkdirs();
        }
        //循环创建每一个实体类
        for (Table table : tableList) {
            boolean isImportBigDecimal = false;
            boolean isImportDate = false;
            //包声明部分
            StringBuffer packageDeclare = new StringBuffer();
            //导入声明部分
            List<String> importDeclare = new ArrayList<String>();
            //类声明部分
            StringBuffer classBeginDeclare = new StringBuffer();
            //私有属性声明部分
            List<String> privatePropertyDeclare = new ArrayList<String>();
            //类声明结束部分
            StringBuffer classEndDeclare = new StringBuffer();
            //包名
            String packageName = this.packageName + "." + "entity." + moduleUrl.replaceAll("/", "") + ".base";
            packageDeclare.append("package " + packageName + ";\r\n\r\n");
            //类声明——开始（将表名首字母大写，去掉_，并将第一个字母大写）
            //拼接后缀生成类名称
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }
            className += "BaseEntity";
            //生成类描述
            classBeginDeclare.append("/**\r\n");
            classBeginDeclare.append(" *" + table.getRemarks() + "\r\n");
            classBeginDeclare.append(" *@author lm \r\n");
            classBeginDeclare.append("**/\r\n");
            classBeginDeclare.append("@Entity\r\n");
            classBeginDeclare.append("@Data\r\n");
            classBeginDeclare.append("@ApiModel(value =\"" + table.getRemarks() + "\",description = \"" + table.getRemarks() + "\")\r\n");
            getLog().info(classBeginDeclare.toString());
            //子类
            classBeginDeclare.append("public class " + className + " extends  BaseEntity{\n");
            //生成类描述——结束
            classEndDeclare.append("\r\n}\r\n");
            //继承基础base
            String basePackageName = this.packageName + "." + "entity";
            importDeclare.add("import " + basePackageName + ".BaseEntity;\r\n");
            importDeclare.add("import javax.validation.constraints.NotNull;\r\n");
            importDeclare.add("import io.swagger.annotations.ApiModelProperty;\r\n");
            importDeclare.add("import javax.persistence.Id;\r\n");
            importDeclare.add("import io.swagger.annotations.ApiModel;\r\n");
            importDeclare.add("import lombok.Data;\r");
            importDeclare.add("import javax.persistence.Entity;\r\n");
            //私有属性，如果是父类才有
            for (Column column : table.getColumnList()) {
                String propertyName = convertColumnNameToPropertyName(column.getName());
                String propertyType = convertSQLTypeToJavaType(column.getTypeName());
                privatePropertyDeclare.add(
                    "\t/**\r\n" +
                        "\t * " + column.getRemarks() + "\r\n" +
                        "\t */\r\n"
                );
                if (column.getIsPk()) {
                    privatePropertyDeclare.add("\t@Id\r");
                }
                if (!column.getIsNotNull()) {
                    privatePropertyDeclare.add("\t@NotNull(message =\"" + column.getRemarks() + "是必填项\")\r");
                    privatePropertyDeclare.add("\t@ApiModelProperty(value = \"" + column.getRemarks() + "\",required = true)\r");
                } else {
                    privatePropertyDeclare.add("\t@ApiModelProperty(value = \"" + column.getRemarks() + "\")\r");
                }
                privatePropertyDeclare.add("\tprivate " + propertyType + " " + propertyName + ";\r\n\r\n");
                if ("BigDecimal".equals(propertyType) && !isImportBigDecimal) {
                    importDeclare.add("import java.math.BigDecimal;\r\n");
                    isImportBigDecimal = true;
                }
                if ("Date".equals(propertyType) && !isImportDate) {
                    importDeclare.add("import java.util.Date;\r\n");
                }

            }
            importDeclare.add("\r\n");
//			写文件操作，如果是子类，文件存在则不写入
            File entityFile = null;
            entityFile = new File(entityPackage, className + ".java");
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(entityFile), Charset.forName("UTF-8")));
                bw.write(packageDeclare.toString());
                for (String importStr : importDeclare) {
                    bw.write(importStr);
                }
                bw.write(classBeginDeclare.toString());
                for (String privatePropertyStr : privatePropertyDeclare) {
                    bw.write(privatePropertyStr.toString());
                }
                bw.write(classEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
            }
        }
    }


    /**
     * 生成基础mapper接口
     *
     * @param tableList
     * @throws IOException
     */
    private void generateBaseAllDao(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //创建Dao存储的包文件夹
        String daoPackage = baseUrl + javaBaseUrl;
        getLog().info(daoPackage);
        String daoPackagePath = daoPackage + packageUrl;
        getLog().info(daoPackagePath);
        daoPackagePath += "/mapper" + moduleUrl + "/base";
        File daoPackageFile = new File(daoPackagePath);
        if (!daoPackageFile.exists()) {
            daoPackageFile.mkdirs();
        }
        String mapperPackageName = this.packageName + "." + "mapper." + moduleUrl.replaceAll("/", "") + ".base";
        //循环创建每一个Dao接口
        for (Table table : tableList) {
            //获取实体类的类名
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }
            //包声明部分
            StringBuffer packageDeclare = new StringBuffer();
            //导入声明部分
            List<String> importDeclare = new ArrayList<String>();
            //Dao接口声明部分
            StringBuffer classBeginDeclare = new StringBuffer();
            //方法声明部分
            List<String> methodDeclare = new ArrayList<String>();
            //Dao接口声明结束部分
            StringBuffer classEndDeclare = new StringBuffer();
            //Dao接口的类型名称
            String daoName = className;
            //包声明
            packageDeclare.append("package " + mapperPackageName + ";\r\n");
            //导入声明部分
            importDeclare.add("\r\n");
            //Dao接口声明——开始
            classBeginDeclare.append("/**\r\n");
            classBeginDeclare.append(" *" + table.getRemarks() + " 数据访问" + "\r\n");
            classBeginDeclare.append(" @author lm\r\n");
            classBeginDeclare.append(" */\r\n");
            classBeginDeclare.append("public interface " + daoName + "BaseMapper{\r\n");
            //Dao接口声明——结束
            classEndDeclare.append("\r\n}\r\n");
            //写文件操作，如果是Dao子接口，文件存在则不写入
            File daoFile = new File(daoPackagePath, daoName + "BaseMapper.java");
//			if (daoFile.exists()) {
//				continue;
//			}
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(daoFile), Charset.forName("UTF-8")));
                bw.write(packageDeclare.toString());
                for (String importStr : importDeclare) {
                    bw.write(importStr);
                }
                bw.write(classBeginDeclare.toString());
                for (String methodStr : methodDeclare) {
                    bw.write(methodStr.toString());
                }
                bw.write(classEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
            }
        }
    }

    /**
     * 生成mapper接口
     *
     * @param tableList
     * @throws IOException
     */
    private void generateAllDao(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //创建Dao存储的包文件夹
        String daoPackage = baseUrl + javaBaseUrl;
        getLog().info(daoPackage);
        String daoPackagePath = daoPackage + packageUrl;
        getLog().info(daoPackagePath);
        daoPackagePath += "/mapper" + moduleUrl;
        File daoPackageFile = new File(daoPackagePath);
        if (!daoPackageFile.exists()) {
            daoPackageFile.mkdirs();
        }
        String mapperPackageName = this.packageName + "." + "mapper." + moduleUrl.replaceAll("/", "");
        //循环创建每一个Dao接口
        for (Table table : tableList) {
            //获取实体类的类名
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }
            //包声明部分
            StringBuffer packageDeclare = new StringBuffer();
            //导入声明部分
            List<String> importDeclare = new ArrayList<String>();
            //Dao接口声明部分
            StringBuffer classBeginDeclare = new StringBuffer();
            //方法声明部分
            List<String> methodDeclare = new ArrayList<String>();
            //Dao接口声明结束部分
            StringBuffer classEndDeclare = new StringBuffer();
            //Dao接口的类型名称
            String daoName = className;
            //包声明
            packageDeclare.append("package " + mapperPackageName + ";\r\n");
            //实体包名
            String packageName = this.packageName + "." + "entity." + moduleUrl.replaceAll("/", "") + "." + daoName + "Entity";
            importDeclare.add("import " + mapperPackageName + ".base." + daoName + "BaseMapper;\r");
            importDeclare.add("import " + packageName + ";\r");
            importDeclare.add("import tk.mybatis.mapper.common.Mapper;\r");
            importDeclare.add("import tk.mybatis.mapper.common.MySqlMapper;\r");
            //导入声明部分
            importDeclare.add("\r\n");
            //Dao接口声明——开始
            classBeginDeclare.append("/**\r\n");
            classBeginDeclare.append(" *" + table.getRemarks() + " 数据访问" + "\r\n");
            classBeginDeclare.append(" @author lm\r\n");
            classBeginDeclare.append(" */\r\n");
            classBeginDeclare.append("public interface " + daoName + "Mapper extends Mapper<" + daoName + "Entity>, MySqlMapper<" + daoName + "Entity>," + daoName + "BaseMapper{\r\n");
            //Dao接口声明——结束
            classEndDeclare.append("\r\n}\r\n");
            //写文件操作，如果是Dao子接口，文件存在则不写入
            File daoFile = new File(daoPackagePath, daoName + "Mapper.java");
//			if (daoFile.exists()) {
//				continue;
//			}
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(daoFile), Charset.forName("UTF-8")));
                bw.write(packageDeclare.toString());
                for (String importStr : importDeclare) {
                    bw.write(importStr);
                }
                bw.write(classBeginDeclare.toString());
                for (String methodStr : methodDeclare) {
                    bw.write(methodStr.toString());
                }
                bw.write(classEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
            }
        }
    }


    /**
     * 生成基础XML映射文件方法
     *
     * @param tableList
     * @throws IOException
     */
    private void generateBaseAllXml(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //创建XML存储的包文件夹
        String xmlPackage = baseUrl + xmlBaseUrl + "mapper" + moduleUrl + "/base";
        System.err.println(xmlPackage);
        getLog().info(xmlPackage);
        String xmlPackagePath = xmlPackage.replaceAll("\\.", "/");
        getLog().info(xmlPackagePath);
        File xmlPackageFile = new File(xmlPackagePath);
        if (!xmlPackageFile.exists()) {
            xmlPackageFile.mkdirs();
        }

        //获取实体类所在的包名
        String entityPackage = this.packageName + "." + "entity." + moduleUrl.replaceAll("/", "");
        String daoPackage = packageName;
        //循环创建每一个XML映射文件
        for (Table table : tableList) {
            //获取实体类的类名
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }
            //XML声明部分
            StringBuffer xmlDeclare = new StringBuffer();
            //<mapper>声明部分
            StringBuffer mapperBeginDeclare = new StringBuffer();
            //<resultMap>声明部分
            StringBuffer resultMapDeclare = new StringBuffer();
            //DAO方法映射声明部分
            List<String> methodDeclare = new ArrayList<String>();
            //<mapper>声明结束部分
            StringBuffer mapperEndDeclare = new StringBuffer();
            //XML声明部分
            xmlDeclare.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
            xmlDeclare.append("<!DOCTYPE mapper\r\n");
            xmlDeclare.append("  PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\r\n");
            xmlDeclare.append("  \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\r\n");

            //<mapper>声明部分
            mapperBeginDeclare.append("<mapper namespace=\"" + daoPackage + ".mapper." + moduleUrl.replaceAll("/", "") + ".base." + className + "BaseMapper" + "\">\r\n");
            //<mapper>声明结束部分
            mapperEndDeclare.append("</mapper>");
            //<resultMap>声明部分
            resultMapDeclare.append("\t<resultMap id=\"BaseResultMap\" " + "type=\"" + entityPackage + ".base." + className + "BaseEntity" + "\">\r\n");
            //	主键映射
            resultMapDeclare.append("\t\t<id column=\"" + table.getPkName() + "\" property=\"" + convertColumnNameToPropertyName(table.getPkName()) + "\" />\r\n");
            //	其它映射
            for (Column column : table.getColumnList()) {
                if (!column.getName().equals(table.getPkName())) {
                    resultMapDeclare.append("\t\t<result column=\"" + column.getName() + "\" property=\"" + convertColumnNameToPropertyName(column.getName()) + "\" />\r\n");
                }
            }
            resultMapDeclare.append("\t</resultMap>\r\n\r\n");
            //写文件操作，如果是XML子映射文件，文件存在则不写入
            File xmlFile = new File(xmlPackagePath, className + "BaseMapper.xml");
            if (xmlFile.exists()) {
                continue;
            }
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(xmlFile), Charset.forName("UTF-8")));
                bw.write(xmlDeclare.toString());
                bw.write(mapperBeginDeclare.toString());
                bw.write(resultMapDeclare.toString());
                for (String methodStr : methodDeclare) {
                    bw.write(methodStr.toString());
                }
                bw.write(mapperEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
                ;
            }
        }
    }


    /**
     * 生成XML映射文件方法
     *
     * @param tableList
     * @throws IOException
     */
    private void generateAllXml(List<Table> tableList) throws IOException {
        if (tableList.isEmpty()) {
            throw new RuntimeException("database is empty...");
        }
        //创建XML存储的包文件夹
        String xmlPackage = baseUrl + xmlBaseUrl + "mapper" + moduleUrl;
        System.err.println(xmlPackage);
        getLog().info(xmlPackage);
        String xmlPackagePath = xmlPackage.replaceAll("\\.", "/");
        getLog().info(xmlPackagePath);
        File xmlPackageFile = new File(xmlPackagePath);
        if (!xmlPackageFile.exists()) {
            xmlPackageFile.mkdirs();
        }

        //获取实体类所在的包名
        String entityPackage = this.packageName + "." + "entity." + moduleUrl.replaceAll("/", "");
        String daoPackage = packageName;
        //循环创建每一个XML映射文件
        for (Table table : tableList) {
            //获取实体类的类名
            String[] classNameStr = table.getName().split("_");
            String className = "";
            for (int i = 0; i < classNameStr.length; i++) {
                className += classNameStr[i].substring(0, 1).toUpperCase() + classNameStr[i].substring(1);
            }
            //XML声明部分
            StringBuffer xmlDeclare = new StringBuffer();
            //<mapper>声明部分
            StringBuffer mapperBeginDeclare = new StringBuffer();
            //<resultMap>声明部分
            StringBuffer resultMapDeclare = new StringBuffer();
            //DAO方法映射声明部分
            List<String> methodDeclare = new ArrayList<String>();
            //<mapper>声明结束部分
            StringBuffer mapperEndDeclare = new StringBuffer();
            //XML声明部分
            xmlDeclare.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
            xmlDeclare.append("<!DOCTYPE mapper\r\n");
            xmlDeclare.append("  PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\r\n");
            xmlDeclare.append("  \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\r\n");

            //<mapper>声明部分
            mapperBeginDeclare.append("<mapper namespace=\"" + daoPackage + ".mapper." + moduleUrl.replaceAll("/", "") + "." + className + "Mapper" + "\">\r\n");
            //<mapper>声明结束部分
            mapperEndDeclare.append("</mapper>");
            //<resultMap>声明部分
            resultMapDeclare.append("\t<resultMap id=\"BaseResultMap\" " + "type=\"" + entityPackage + "." + className + "Entity" + "\""
                + " extends=\"" + daoPackage + ".mapper." + moduleUrl.replaceAll("/", "") + ".base." + className + "BaseMapper.BaseResultMap\">\r\n\r\n");
            resultMapDeclare.append("\t</resultMap>\r\n\r\n");
            //写文件操作，如果是XML子映射文件，文件存在则不写入
            File xmlFile = new File(xmlPackagePath, className + "Mapper.xml");
            if (xmlFile.exists()) {
                continue;
            }
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(xmlFile), Charset.forName("UTF-8")));
                bw.write(xmlDeclare.toString());
                bw.write(mapperBeginDeclare.toString());
                bw.write(resultMapDeclare.toString());
                for (String methodStr : methodDeclare) {
                    bw.write(methodStr.toString());
                }
                bw.write(mapperEndDeclare.toString());
            } finally {
                if (bw != null) {
                    bw.close();
                }
                ;
            }
        }
    }

    /**
     * 转换表字段名 到 类属性名 方法
     *
     * @param columnName
     * @return
     */
    private String convertColumnNameToPropertyName(String columnName) {
        //去掉表字段名前缀部分
        //String propertyName = columnName.substring(columnName.indexOf("_")+1 );
        System.out.println(columnName);
        String propertyName = columnName.substring(0, 1).toLowerCase() + columnName.substring(1);
        //后续如果存在下划线，则去掉下划线，后续单词首字母大写
        if (propertyName.contains("_")) {
            String[] propertyNames = propertyName.split("_");
            propertyName = propertyNames[0];
            for (int i = 1; i < propertyNames.length; i++) {
                propertyName += propertyNames[i].substring(0, 1).toUpperCase() + propertyNames[i].substring(1);
            }
        }

        return propertyName;
    }

    /**
     * 转换SQL数据类型名 到 Java数据类型名 方法
     *
     * @param typeName
     * @return
     */
    private String convertSQLTypeToJavaType(String typeName) {
        String propertyType = "BIGINT".equals(typeName) ? "Long" :
            "INT".equals(typeName) ? "Integer" :
                "BIGINT".equals(typeName) ? "Long" :
                    "TINYINT".equals(typeName) ? "Integer" :
                        "DECIMAL".equals(typeName) ? "BigDecimal" :
                            "VARCHAR".equals(typeName) ? "String" :
                                "TEXT".equals(typeName) ? "String" :
                                    "DATETIME".equals(typeName) ? "Date" :
                                        "TIMESTAMP".equals(typeName) ? "Date" :
                                            "DECIMAL".equals(typeName) ? "BigDecimal" :
                                                "CHAR".equals(typeName) ? "String" :
                                                    "TINYINT".equals(typeName) ? "Integer" :
                                                        "DATE".equals(typeName) ? "Date" :
                                                            "DOUBLE".equals(typeName) ? "Double" :
                                                                "FLOAT".equals(typeName) ? "Float" :
                                                                    "CURRENT_TIMESTAMP".equals(typeName) ? "Date" :
                                                                        "LONGTEXT".equals(typeName) ? "String" :
                                                                            "error: " + typeName;
        if (propertyType.startsWith("error:")) {
            throw new RuntimeException("unkonw column type " + propertyType);
        }
        return propertyType;
    }

}
